package com.gph.saviorframework.shiro;

import com.gph.saviorframework.common.model.User;
import com.gph.saviorframework.security.service.FunctionService;
import com.gph.saviorframework.security.service.RoleService;
import com.gph.saviorframework.security.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;

public class ShiroDbRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private FunctionService functionService;

    @Autowired
    private RoleService roleService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = StringUtils.EMPTY;
        Object object = principals.getPrimaryPrincipal();
        if(object instanceof String){
            username = object.toString();
        }
        else if(object instanceof User){
            username = ((User)object).getUsername();
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //todo:此处设置权限信息
        info.addStringPermissions(functionService.findFunctionsByUserId(username));

        List<Map<String,Object>> res = roleService.findByUser(username);

        for(Map<String,Object> map : res){
            if((Boolean)map.get("checked")){
                info.addRole(map.get("id").toString());
            }
        }

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken authcToken = (UsernamePasswordToken)token;

        String accountName = authcToken.getUsername();

        if(StringUtils.isEmpty(accountName)){
            throw new AuthenticationException("Username can not NULL");
        }
        User user = userService.findByCertificateNum(accountName);

        if(user==null){
            throw new UnknownAccountException("Username or Password is wrong");
        } else if(!user.isEnabled()) {
            throw new ExcessiveAttemptsException("User is enabled");
        }

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword().toCharArray(),getName());

        return simpleAuthenticationInfo;
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
}
